 
#include <AT89X51.h>
#include <stdio.h>
#include <intrins.h>
typedef unsigned char uchar;
typedef unsigned int  uint;
//********************** DS18B20 指令*********************
#define ds18B20_READ_ROM          0x33      // 读ROM指令
#define ds18B20_MATCH_ROM         0x55      // 匹配ROM指令
#define ds18B20_SKIP_ROM          0xCC      // 跳过ROM指令
#define ds18B20_SEARCH_ROM        0xF0      // 搜索ROM指令
#define ds18B20_ALARM_SEARCH      0xEC      // 报警搜索指令
#define ds18B20_WRITE_SCRATCHPAD  0x4E      // 写暂存寄存器指令
#define ds18B20_READ_SCRATCHPAD   0xBE      // 读暂存寄存器指令
#define ds18B20_COPY_SCRATCHPAD   0x48      // 复制暂存寄存器指令
#define ds18B20_CONVERT_T         0x44      // 启动温度转换指令
#define ds18B20_RECALL_E2         0xB8      // 重新调出E2PROM的数据
#define ds18B20_READ_POWER_SUPPLY 0xB4      // 读电源
#define out P0
sbit ds18B20_data = P3^7;        //温度探头数据端口对应的单片机引脚
sbit smg1=out^4;
sbit smg2=out^5;
//*********************温度探头程序************************
bit   Rstds18B20(void);           // DS18B20复位程序, 返回0-有设备连接,1-无设备连接
void  Writeds18B20(uchar );       // 写一个字节ds18B20数据、命令子程序
uchar Readds18B20(void);          // 读一个字节ds18B20数据子程序
uint  GetTempValue(void);         // 启动ds18B20温度转换程序
void Delay_15us(uint);
void delay5(uchar);
void Delay_10us(void);
//******************************************************************
//                       主程序
//******************************************************************

void delay5(uchar n){
    do {
      _nop_();
      _nop_();
      _nop_();
      n--;
    } while(n);
 }

void main(void){
  uchar i,temp;
  delay5(1000);
  while(1){
    temp = Readds18B20();
    for(i=0; i<10; i++){
      out = (temp/10)&0x0f;
      smg1 = 0;
      smg2 = 1;
      delay5(1000);
      out = (temp%10)&0x0f;
      smg1 = 1;
      smg2 = 0;
      delay5(1000);
    } 
  }
}

//******************************************************************
//                       ds18B20复位程序
//******************************************************************
bit Rstds18B20(void)              // 返回,0-有设备连接;1-无设备连接
{
 uchar i;
 bit RstFlag;
 RstFlag = 1;
 ds18B20_data = 1;
 _nop_();
 ds18B20_data = 0;         // 发送复位脉冲，时间>480us
 Delay_15us(40);           // 延时480--960us
 ds18B20_data = 1;         // 拉高总线，延时15us-60us后等待ds18B20响应
 Delay_15us(2);            // 15us-60us
 for (i=0;i<6;i++)   // 60us-240us
   {
      Delay_15us(1);
      if (ds18B20_data==0)
      RstFlag=0;           // 接收ds18B20的存在信号
   }
 Delay_15us(15);           //  240us
 return RstFlag;
}
//*******************写一个字节ds18B20数据、命令子程序******************
//功能：向ds18B20写入数据或命令
//入口：待写入ds18B20的数据或命令
//出口：无
//******************************************************************
void Writeds18B20(uchar ch)
{
 uchar i;
 ds18B20_data = 1;               // 拉高总线，延时1us，准备启动
 _nop_();
 for (i=0;i<8;i++)
     {
  ds18B20_data = 0;       // 拉低总线
                Delay_10us();           // 延时10us
  ds18B20_data = ch&0x1;  // 发送待写入的数据，“1”或“0”
  Delay_15us(2);          // 保持写入数据时间45us
  ds18B20_data = 1;       // 拉高总线，延时1us后准备下一位传输
  ch = ch>>1;             //先写低位，后写高位
  _nop_();
     }
}
//******************读一个字节ds18B20数据子程序************************
//功能：从ds18B20读出数据
//入口：无
//出口：读出的ds18B20的数据
//******************************************************************
uchar Readds18B20(void)
{
 uchar i,ch;
 ch = 0;
 ds18B20_data = 1;                // 拉高总线，延时1us，准备启动
 _nop_();
 for (i=0;i<8;i++)
     {
  ds18B20_data = 0;        // 拉低总线
  Delay_10us();            // 延时10us
                ds18B20_data = 1;        // 拉高总线，准备接收数据
  _nop_();
  ch = ch>>1;
  if (ds18B20_data == 1)   // 接收ds18B20的数据
    ch = ch+0x80;
  Delay_15us(2);           // 延时45us，保证整个读命令有60us
     }
 return ch;
}

//*************************启动ds18B20温度转换程序*********************
//功能：读取18B20的温度值
//入口：无
//出口：0xffff－18B20不正常
//      0x8000－温度低于零度
//      0~1250－摄氏温度(0~125)
//******************************************************************
uint GetTempValue(void)
{
 uchar i=0,j=0;
 uint T=0;
 if(!Rstds18B20())                                   //如果探头连接正常
  {
  Rstds18B20();                               // 复位ds18B20
  Writeds18B20(ds18B20_SKIP_ROM);             // 跳过ROM操作
  Writeds18B20(ds18B20_CONVERT_T);            // 启动ds18B20温度转换
  if(!Rstds18B20())                           //如果探头连接正常
    {
      Rstds18B20();                            // 复位ds18B20
      Writeds18B20(ds18B20_SKIP_ROM);          // 跳过ROM操作
      Writeds18B20(ds18B20_READ_SCRATCHPAD);   // 发读ds18B20数据，前两位是温度值
      i = Readds18B20();                       // 温度值的低位数据
      j = Readds18B20();                       // 温度值的高位数据
      T = i+(j<<8);
      if (T==0xffff)
                        return 0xffff;
                    if (T>0x8000)                   //如果温度低于0度
     return 0x8000;
      else
            return (T*5/8);
      }
              else
         {return 0xffff;}
 }
      else
      {return 0xffff;}
}
//*****************************************
//          延时10us
//*****************************************
void Delay_10us(void)
{
    _nop_();
    _nop_();
    _nop_();
}
//******************************************
//            延时time*15us
//  延时时间等于time*15us
//******************************************
void Delay_15us(uint time)
{
        uint i;
 for (i=0;i<time;i++) ;
}
